#include "Ai.hpp"
#include "Variant.hpp"
#include "world.hpp"
#include <iostream>

//lancement du jeu : dans le dossier COW, lancer la commande :
//./cow.sh -q -g FruitSalad -a Stras -a DeGuio -z map1.txt
using namespace std;

Ai ai = Ai();

Ai::Ai() {
	communicator = new SpecificCommunicator(this);
	api = new SpecificApiConnector();
	setbuf(stdout, 0);
}

Ai::~Ai() {
	delete api;
	delete communicator;
}

void Ai::stop() {
	cout << AI_NAME << " : stop" << endl;
	world.printInfos();
}

// User-defined functions
void Ai::initGame(IntMatrix2 architecture,
		IntMatrix2 fruits, IntMatrix2 buildings,
		int limitCherry, int limitKiwi, int limitNut,
		int vitaminGoal, int maxNbTurns) {
    //Charge les valeurs de l'initialisation dans la map et le monde
    cout << AI_NAME << " : initGame" << endl;
    cout << "But : " << vitaminGoal << endl;
    cout << "Ntours : " << maxNbTurns << endl;
    world.initWorld(architecture, fruits, buildings, limitCherry, limitKiwi, limitNut, vitaminGoal, maxNbTurns);
    //strat.init();
}

void Ai::playTurn(IntMatrix2 newObjects,
	IntMatrix1 deletedObjects, IntMatrix2 movedFruits,
	IntMatrix2 modifiedFruits, IntMatrix2 modifiedSugarDrops) {
    cout << AI_NAME << " : playTurn" << endl;
    //Met à jour le monde
    world.updateAtBeginningOfTurn(newObjects, deletedObjects, movedFruits, modifiedFruits, modifiedSugarDrops);

    //world.printInfos();

    strat.run();
    /*map_chunk * dest = getFreeSpaceAround(world.ourSugarBowl.position);
    cout << world.ourSugarBowl.position->X_coord << "," << world.ourSugarBowl.position->Y_coord << endl;
    if (dest == NULL) {
        cout << "Pas de case libre !!!";
    } else {
        int ret = world.ourFruits.begin()->second.move(dest->X_coord, dest->Y_coord);
        cout << dest->X_coord << "," << dest->Y_coord << endl;
        cout << api->decode(ret) << endl;
    }*/

    /*if (world.getVitaminCount() >= 20) {
        world.fructify(FRUIT_CHERRY,
                 world.ourFructificationTank.position->X_coord + 1,
                 world.ourFructificationTank.position->Y_coord);
    }*/

    /*map<id, Fruit>::iterator it = world.ourFruits.begin();
    it++;
    Fruit &leFruit = it->second;
    int res = leFruit.move(leFruit.getPosX()+1, leFruit.getPosY());
    cout << api->decode(res) << endl;*/
/*
	cout << "VitaminCpp: Play Turn..." << endl;

	// Display new objects
	cout << "== New objects ==" << endl;
	for (int i = 0; i < newObjects.size(); i++) {
		cout << "New object: "
			<< api->decode(newObjects[i][OBJECT_TYPE]) << " " << "id #"
			<< newObjects[i][OBJECT_ID] << " at ("
			<< newObjects[i][OBJECT_X] << ";"
			<< newObjects[i][OBJECT_Y] << ") ; info="
			<< newObjects[i][OBJECT_INFO] << endl;
	}
	cout << endl;

	// Display deleted objects
	cout << "== Deleted objects ==" << endl;
	for (int i = 0; i < deletedObjects.size(); i++) {
		cout << "Object: id #" << deletedObjects[i] << " deleted" << endl;
	}
	cout << endl;

	// Display moved fruits objects
	cout << "== Moved fruits ==" << endl;
	for (int i = 0; i < movedFruits.size(); i++) {
		cout << "Fruit: id #" << movedFruits[i][OBJECT_ID]
			<< " moved from (" << movedFruits[i][OBJECT_X] << ";"
			<< movedFruits[i][OBJECT_Y] << ") to ("
			<< movedFruits[i][OBJECT_NEW_X] << ";"
			<< movedFruits[i][OBJECT_NEW_Y] << ")" << endl;
	}
	cout <<  endl;

	// Display modified fruits objects
	cout << "== Modified fruits ==" << endl;
	for (int i = 0; i < modifiedFruits.size(); i++) {
		cout << "Fruit: id #" << modifiedFruits[i][OBJECT_ID]
			<< " now has " << modifiedFruits[i][OBJECT_LIFE] << " PV and "
			<< modifiedFruits[i][OBJECT_DEFENSE] << " Def" << endl;
	}
	cout << endl;

	// Display modified sugar drops objects
	cout << "== Modified sugar drops ==" << endl;
	for (int i = 0; i < modifiedSugarDrops.size(); i++) {
		cout << "Sugar drop: id #"
			<< modifiedSugarDrops[i][OBJECT_ID] << " now has "
			<< modifiedSugarDrops[i][OBJECT_SUGAR] << " sugar grains" << endl;
	}
	cout << endl;

	cout << "== Test Game API ==" << endl;
	// Test game API functions
	testGameApi();*/
}

void Ai::mapUpdate(IntMatrix2 newObjects, IntMatrix2 modifiedSugarDrops) {
    //Met à jour le monde
    cout << AI_NAME << " : mapUpdate callback" << endl;
    world.updateDuringTurn(newObjects, modifiedSugarDrops);


	/*cout << "VitaminCpp: Map update..." << endl;

	// Display new objects
	cout << "== New objects ==" << endl;
	for (int i = 0; i < newObjects.size(); i++) {
		cout << "New object: "
			<< api->decode(newObjects[i][OBJECT_TYPE]) << " " << "id #"
			<< newObjects[i][OBJECT_ID] << " at ("
			<< newObjects[i][OBJECT_X] << ";"
			<< newObjects[i][OBJECT_Y] << ") ; info="
			<< newObjects[i][OBJECT_INFO] << endl;
	}
	cout << endl;

	// Display modified sugar drops objects
	cout << "== Modified sugar drops ==" << endl;
	for (int i = 0; i < modifiedSugarDrops.size(); i++) {
		cout << "Sugar drop: id #"
			<< modifiedSugarDrops[i][OBJECT_ID] << " now has "
			<< modifiedSugarDrops[i][OBJECT_SUGAR] << " sugar grains" << endl;
	}
	cout << endl;*/
}
